#include "gplib.h"
#include <math.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
/*
отрисовка шрифтов - тестируется, пока только 8 бит
*/

extern const int g_nByteOffset[4];


const struct TFont* SetFont(TGraphicContext* ctx,const struct TFont* pFont)
{
	struct TFont* pOldFont=ctx->pCurrFont;
	if(pFont!=0)
		ctx->pCurrFont=pFont;
	return pOldFont;
}

const struct TFont* GetCurrFont(TGraphicContext* ctx)
{
	return ctx->pCurrFont;
}
int GetFontWidth(TGraphicContext* ctx)
{
	return ctx->pCurrFont->nWidth;
}
int GetFontheight(TGraphicContext* ctx)
{
	return ctx->pCurrFont->nHeight;
}
/**
 * OutChar - Вывод в текущую точку символа текущим шрифтом.
 * @param ctx - указатель на графический контекст.
 * @param Symbol - выводимый символ.
 * @param Color - цвет символа.
 * */
void OutChar(TGraphicContext* ctx, unsigned char Symbol,char Color)
{
	const unsigned char *SPtr=ctx->pCurrFont->pData+Symbol*ctx->pCurrFont->nHeight;//указатель на содержимое шрифта
	unsigned char ch;//текущий байт в шрифте
	unsigned char Mask;//Маска для выделения пикселей в шрифте
	int FHeight=ctx->pCurrFont->nHeight;//высота шрифта
	int BytesScreenWidth=ctx->nBytesPerLine;//Байт в одной строке шрифта
    char* ScreenPos=ctx->pData+ctx->nLastPositionY*BytesScreenWidth+ctx->nLastPositionX;//указатель на текущую позицию в контексте
	char BytesPerSymbolLn=ctx->pCurrFont->nBytesPerSymbolLine;
	int BitsInLastByte=ctx->pCurrFont->nBitsInLastByte;
	int i,j,k;
	//Проверки возможности вывода символа
	if(ctx->nLastPositionX+ctx->pCurrFont->nWidth > ctx->nScreenSizeX || ctx->nLastPositionY+ctx->pCurrFont->nHeight > ctx->nScreenSizeY)//если символ не помещается, не рисуем
		return;
	for(i=0;i<FHeight;i++)
	{
	    for(j=0;j<BytesPerSymbolLn-1;++j)//проход по всем байтам строки символа кроме последнего, возможно неполного
	    {

	    	Mask=0x80;
	        ch=*SPtr;
	        for(k=0;k<8;k++)
	        {
	        	if(ch&Mask)
	        	{
	        		*(BYTE_REORDER(ScreenPos+k))=Color;
	        	}
	            Mask>>=1;
	        }
	        SPtr++;
	    }
	    {//проход по последнему байту строки символа
	    	Mask=0x80;
	    	ch=*SPtr;
	    	for(k=0;k<BitsInLastByte;k++)
	    	{
	    		if(ch&Mask)
	    	  	{
	    			*(BYTE_REORDER(ScreenPos+k))=Color;
	    	  	}
	    	  	Mask>>=1;
	    	}
	    	SPtr++;
	     }
	     ScreenPos+=BytesScreenWidth;
	}
}

/**
 * OutCharBackground - Вывод в текущую позицию символа с фоном.
 * @param ctx - указатель на графический контекст.
 * @param Symbol - выводимый символ.
 * @param Color - цвет символа.
 * @param BackgroundColor - цвет фона символа.
 * */
void OutCharBackground(TGraphicContext* ctx, unsigned char Symbol,char Color, char BackgroundColor)
{
	const unsigned char *SPtr=ctx->pCurrFont->pData+Symbol*ctx->pCurrFont->nHeight;//указатель на содержимое шрифта
	unsigned char ch;//текущее значение байта в шрифте
	unsigned char Mask;//маска для выделения пикселя в шрифте
	int FHeight=ctx->pCurrFont->nHeight;//Высота шрифта
	int ByteScreenWidth=ctx->nBytesPerLine;//Байтовая ширина экрана
    char* ScreenPos=ctx->pData+ctx->nLastPositionY*ByteScreenWidth+ctx->nLastPositionX;//указатель на текущую позицию в контексте
	char BytesPerSymbolLn=ctx->pCurrFont->nBytesPerSymbolLine;//Число байт в строке шрифта
	int BitsInLastByte=ctx->pCurrFont->nBitsInLastByte;//Число бит в последнем байте строки шрифта
	int i,j,k;
	if(ctx->nLastPositionX+ctx->pCurrFont->nWidth > ctx->nScreenSizeX || ctx->nLastPositionY+ctx->pCurrFont->nHeight > ctx->nScreenSizeY)//если символ не помещается, не рисуем
		return;
	for(i=0;i<FHeight;i++)
	{
	    for(j=0;j<BytesPerSymbolLn-1;++j)//проход по всем байтам строки символа кроме последнего, возможно неполного
	    {
	    	Mask=0x80;
	        ch=*SPtr;
	        for(k=0;k<8;k++)
	        {
	        	if(ch&Mask)
	        	{
	        		*(BYTE_REORDER(ScreenPos+k))=Color;
	        	}
	        	else
	        	{
	        		*(BYTE_REORDER(ScreenPos+k))=BackgroundColor;
	        	}
	            Mask>>=1;
	        }
	        SPtr++;
	    }
	    {//проход по последнему байту строки символа
	    	Mask=0x80;
	    	ch=*SPtr;
	    	for(k=0;k<BitsInLastByte;k++)
	    	{
	    		if(ch&Mask)
	    	  	{
	    			*(BYTE_REORDER(ScreenPos+k))=Color;
	    	  	}
	    		else
	    		{
	    			*(BYTE_REORDER(ScreenPos+k))=BackgroundColor;
	    		}
	    	  	Mask>>=1;
	    	}
	    	SPtr++;
	     }
	     ScreenPos+=ByteScreenWidth;
	}
}

/**
 * OutText - вывод текста в графический контекст текущим шрифтом.
 * @param ctx - указатель на графический контекст.
 * @param string - указатель на строку. Константный.
 * @param color - цвет шрифта.
 * @param length -
 * */
void OutText(TGraphicContext* ctx,const char *string,char color,int length)
{
   //massert(string);
   //massert(LastPositionY+(int)FHeight<=ScreenSizeY);
   //massert(LastPositionX+(int)FWidth*length<=ScreenSizeX);
   int FontWidth=ctx->pCurrFont->nWidth;
   int i=0;
   if(string==0 || ctx->nLastPositionY+ctx->pCurrFont->nHeight > ctx->nScreenSizeY )
	   return;
   if(ctx->nLastPositionX+ctx->pCurrFont->nWidth*length > ctx->nScreenSizeX)//Если вся строка не помещается на экране.
   {
	   length=(ctx->nScreenSizeX-ctx->nLastPositionX)/ctx->pCurrFont->nWidth;//Будем рисовать столько, сколько поместится.

   }
   for(i=0;i<length && string[i]!=0;i++)
   {
	  OutChar(ctx,string[i],color);
      ctx->nLastPositionX+=FontWidth-1;
   }
}
/**
 * */
void OutTextBackground(TGraphicContext* ctx,const char *string,int length,char color,char colorB)
{
   //massert(string);
   //massert(LastPositionY+(int)FHeight<=ScreenSizeY);
   //massert(LastPositionX+(int)FWidth*length<=ScreenSizeX);
   int FontWidth=ctx->pCurrFont->nWidth;
   int i=0;
   if(string==0 || ctx->nLastPositionY+ctx->pCurrFont->nHeight > ctx->nScreenSizeY || ctx->nLastPositionX+ctx->pCurrFont->nWidth*length > ctx->nScreenSizeX)
	   return;
   for(i=0;i<length && string[i]!=0;i++)
   {
	  OutCharBackground(ctx,(unsigned char)string[i],color,colorB);
      ctx->nLastPositionX+=FontWidth-1;
   }
}

void OutFormatText(TGraphicContext* ctx, char color,const char *format,...)
{
   char str[512];
   //massert(format);
   if(format==0)
	   return;
   va_list ap;
   va_start(ap,format);
#ifdef _MUPD_BAGET_PLATFORM
   massert(vsprintf(str,format,ap)<(int)sizeof(str)); // RT OS BAGET has not vsnprintf()  :-(((
#else
   vsnprintf(str,sizeof(str),format,ap);
#endif
   str[sizeof(str)-1]='\0';
   va_end(ap);
   OutText(ctx,str,color,strlen(str));
}

void OutFormatTextB(TGraphicContext* ctx, char color,char colorB,const char *format,...)
{  char str[512];
   //massert(format);
	if(format==0)
		return;
   va_list ap;
   va_start(ap,format);
#ifdef _MUPD_BAGET_PLATFORM
   massert(vsprintf(str,format,ap)<(int)sizeof(str)); // RT OS BAGET has not vsnprintf()  :-(((
#else
   vsnprintf(str,sizeof(str),format,ap);
#endif
   str[sizeof(str)-1]='\0';
   va_end(ap);
   OutTextBackground(ctx,str,strlen(str),color,colorB);
}

